package com.mjk.manager.task.type.sqlhttp.http;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.PostConstruct;

import com.mjk.common.base.constns.BeeCommonConstns;
import com.mjk.common.base.error.BeeError;
import com.mjk.common.base.error.BizException;
import com.mjk.common.core.jdbc.service.parse.type.BeeParseType;
import com.mjk.common.tools.gson.GsonUtils;
import com.mjk.common.tools.logger.BizLogger;
import com.mjk.common.tools.springextend.BeeApplicationListener;
import com.mjk.common.util.*;
import com.mjk.manager.task.type.sqlhttp.http.encry.DefaultHttpSyncEncry;
import com.mjk.manager.task.type.sqlhttp.http.encry.IHttpSyncEncry;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.stereotype.Component;

import lombok.Data;

@Component
public class HttpSyncStrategy implements BeeApplicationListener {
	
	private  Integer MAX_POOL_SIZE = 500;
	
	private  Integer MAX_QUERE_NUMBER = 5000;
	
	private boolean running = false;
	
	public HttpSyncStrategy(){
		running = true;	
		initMethod();
	}
	/**
	 * 队列
	 */
	protected  final BlockingQueue<HttpSyncContent> queue=new ArrayBlockingQueue<>(MAX_QUERE_NUMBER);
	/**
	 * 线程池
	 */
	private  final ExecutorService pool=Executors.newFixedThreadPool(MAX_POOL_SIZE, new CustomizableThreadFactory("DefaultConver"));
	
	public void pushContent(HttpSyncContent content) {
		if("0".equals(content.getAsyn())) {
			syncResource(content);
		}else {
			try {
				content.setTranceId(MDCUtils.getTraceId());
				queue.put(content);
			} catch (Exception e) {
				BizLogger.error(e);
				Thread.currentThread().interrupt();
			}
		}
	}
	
	@PostConstruct
	public void initMethod() {
		pool.execute(()->{
			while(running){
				try{
					syncResource(queue.take());
				}catch(Exception e){
					BizLogger.error(e);
					Thread.currentThread().interrupt();
				}
			}
		});
	}
	/**
	 * 发送具体得内容
	 * @param content
	 */
	public void syncResource(HttpSyncContent content) {
		//查看获取得参数是否是List 如果是LIST 需要循环发送
		if(ObjectUtils.isEmpty(content.getUrl())) {
			return ;
		}
		if(!ObjectUtils.isEmpty(content.getTranceId()))
			MDCUtils.setTraceId(content.getTranceId());
		//判断URL地址是否是正常的url地址
		Pattern urlPattern = Pattern.compile(BeeCommonConstns.HTTP_MATCH);
		Matcher urlMatcher = urlPattern.matcher(content.getUrl());
		if(!urlMatcher.find()) {
			throw new BizException(content.getUrl() + "is not a match url");
		}
		Map<String,Object> reqParams = content.getRequestParams();
		IHttpSyncEncry encry = null;
		if(ObjectUtils.isEmpty(content.getEncry())) {
			encry = new DefaultHttpSyncEncry();
		}else {
			Class<?> clazz = ClassUtil.loadClass(content.getEncry());
			if(clazz.isAssignableFrom(IHttpSyncEncry.class)) {
				try {
					encry = (IHttpSyncEncry) clazz.newInstance();
				} catch (Exception e) {
					throw new BizException(BeeError.SYSTEM_ERROR_SYNC_ENCY_CLASS_ERROR.getMsg());
				} 
			}else {
				throw new BizException(BeeError.SYSTEM_ERROR_SYNC_ENCY_CLASS_ERROR.getMsg());
			}
		}
		List<String> params = encry.getSyncParams(reqParams,content.getParamsTemplate());
		for(String param : params) {
			String result = HttpUtils.httpPost(content.getUrl(), param, encry.getSyncHeader(reqParams));
			if(ObjectUtils.isNotEmpty(content.getResponseSql())){//如果返回的SQL 不为空，则需要执行
				BeeParseType.getParsing(BeeParseType.SQL).parsing(content.getResponseSql(), GsonUtils.json2Map(result));
			}
		}
	}

	/**
	 * http 资源推送内容
	 * 
	 * @author Administrator
	 *
	 */
	@Data
	public static class HttpSyncContent {
		/**
		 * 请求地址
		 */
		private String url;
		/**
		 * 加密方式类 入参为 workflow 中的inparams
		 */
		private String type;
		/**
		 * 加密方式类 入参为 workflow 中的inparams
		 */
		private String encry;
		/**
		 * 参数模板 http webservice 为soapui工具里面提取的报文信息
		 */
		private String paramsTemplate;
		/**
		 * 请求类型 post /get 默认post
		 */
		private Map<String,Object> requestParams;
		/**
		 * 请求返回参数 用于后续任务
		 */
		private String responseSql;
		/**
		 * 是否异步请求 0 不是 1是
		 */
		private String asyn;
		/**
		 * 日志追踪码
		 */
		private String tranceId;
	}
}
